package com.cosmoplat.xikai.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cosmoplat.xikai.business.domain.*;
import com.cosmoplat.xikai.business.domain.back.EquipmentStatusBackup;
import com.cosmoplat.xikai.business.domain.back.EquipmentUseBackup;
import com.cosmoplat.xikai.business.domain.back.ProcessingDataBack;
import com.cosmoplat.xikai.business.enums.DeviceParamsEnum;
import com.cosmoplat.xikai.business.enums.DeviceRunStatusEnum;
import com.cosmoplat.xikai.business.enums.DeviceWarnEnum;
import com.cosmoplat.xikai.business.mapper.EquipmentStatusBackupMapper;
import com.cosmoplat.xikai.business.mapper.EquipmentUseBackupMapper;
import com.cosmoplat.xikai.business.mapper.ProcessingDataMapper;
import com.cosmoplat.xikai.business.scada.ScadaData;
import com.cosmoplat.xikai.business.service.BackService;
import com.cosmoplat.xikai.business.service.DeviceLogService;
import com.cosmoplat.xikai.business.service.FaultConfigurationService;
import com.cosmoplat.xikai.common.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

import static com.cosmoplat.xikai.common.utils.DateUtils.YYYY_MM_DD_HH_MM_SS;

/**
 * @ClassName BackServiceImpl
 * @Description 备份表-服务
 * @Author wdf
 * @Date 2025/2/6
 */
@Slf4j
@Service
public class BackServiceImpl implements BackService {

    @Autowired
    private EquipmentStatusBackupMapper equipmentStatusBackupMapper;

    @Autowired
    private EquipmentUseBackupMapper equipmentUseBackupMapper;

    @Autowired
    private ProcessingDataMapper processingDataMapper;

    @Autowired
    private FaultConfigurationService faultConfigurationService;

    @Autowired
    private DeviceLogService deviceLogService;

    @Autowired
    private ScadaData scadaData;

    @Value("${device.code}")
    private String deviceCode;


    @Override
    public void insertEquipmentStatusBackup(DeviceLog deviceLog) {
        // 获取物模型
        DeviceThingModel deviceThingModel = scadaData.getDeviceThingModel(deviceCode, String.valueOf(deviceLog.getDeviceThingModelId()), 3);

        EquipmentStatusBackup statusBackup = new EquipmentStatusBackup();
        statusBackup.setDeviceCode(deviceCode);
        statusBackup.setPrimaryKey(deviceLog.getId());
        statusBackup.setStatusTime(DateUtils.parseDateToStr(YYYY_MM_DD_HH_MM_SS, deviceLog.getDataTime()));
        
        // 只记录告警点位，运行状态
        if (DeviceWarnEnum.isWarningPoint(deviceThingModel.getIdentifier())) {
            statusBackup.setDeviceStatus("故障");
            statusBackup.setStatusCode("3");
        } else if (DeviceParamsEnum.RUN_STATE.getName().equals(deviceThingModel.getIdentifier())) {
            setStatusCode(deviceLog, statusBackup);
        } else {
            return;
        }

        if (deviceThingModel != null) {
            FaultConfiguration faultConfiguration = faultConfigurationService.getOne(new LambdaQueryWrapper<FaultConfiguration>().eq(FaultConfiguration::getFaultName, deviceThingModel.getIdentifier()));
            statusBackup.setMalfunctionCode(faultConfiguration.getFaultCode());
            statusBackup.setMalfunctionName(faultConfiguration.getFaultName());
            statusBackup.setMalfunctionExplain(faultConfiguration.getFaultDescription());
        }

        String val = deviceLog.getVal();
        // 获取上一条记录
        QueryWrapper<EquipmentStatusBackup> wrapper = new QueryWrapper<>();
        wrapper.select(" top  1  * ")
                .eq("MalfunctionName", deviceThingModel.getIdentifier())
                .orderByDesc("StatusTime");
        List<EquipmentStatusBackup> list = equipmentStatusBackupMapper.selectList(wrapper);
        EquipmentStatusBackup latsDeviceLog = null;
        if (CollectionUtils.isNotEmpty(list)) {
            latsDeviceLog = list.get(0);
            if (latsDeviceLog.getAlarmRemove() == null) {
                latsDeviceLog.setAlarmRemove("1");
            }
        } else {
            // 之前没有告警记录
            latsDeviceLog = new EquipmentStatusBackup();
            latsDeviceLog.setAlarmRemove("0");
        }


        // 本次 未告警
        if (val != null && val.equals("0")) {
            if (latsDeviceLog != null) {
                // 上一次记录是 告警 ,本次未告警 -> 告警解除
                if (latsDeviceLog.getAlarmRemove().equals("1")) {
                    log.debug("上一次记录是 告警 ,本次未告警 -> 告警解除");
                    statusBackup.setAlarmRemove("0");

                    // 检查是否还有其他告警
                    ArrayList<String> warningList = DeviceWarnEnum.getIdentiflerList();
                    Boolean hasWarning = false;
                    for (String name : warningList) {
                        DeviceLog deviceLogWarning = scadaData.getDeviceLog(name);
                        if (deviceLogWarning != null && deviceLogWarning.getVal().equals("1")) {
                            log.debug("报警解除时，还有报警存在：{}", deviceLogWarning);
                            hasWarning = true;
                        }
                    }

                    // 告警全部解除，保存一条运行状态
                    if (!hasWarning) {
                        EquipmentStatusBackup runStatusRecord = new EquipmentStatusBackup();
                        DeviceLog deviceLogWarning = scadaData.getDeviceLog(DeviceParamsEnum.RUN_STATE.getName());
                        if (deviceLogWarning != null) {
                            runStatusRecord.setAlarmRemove("0");
                            runStatusRecord.setDeviceCode(deviceCode);
                            runStatusRecord.setPrimaryKey(deviceLogWarning.getId());
                            runStatusRecord.setStatusTime(DateUtils.parseDateToStr(YYYY_MM_DD_HH_MM_SS, deviceLogWarning.getDataTime()));
                            setStatusCode(deviceLog, runStatusRecord);
                            equipmentStatusBackupMapper.insert(runStatusRecord);
                        }
                    }

                } else {
                    // 上一次记录是 未告警 ,本次未告警 -> 重复，不记录
                    //log.debug("上一次记录是 未告警 ,本次未告警 -> 重复，不记录");
                    return;
                }
            }
            // 本次告警
        } else if (val != null && val.equals("1")) {
            if (latsDeviceLog != null) {
                // 上一次记录是 告警 ,本次告警 -> 告警持续,不记录
                if (latsDeviceLog.getAlarmRemove().equals("1")) {
                    log.debug("上一次记录是 告警 ,本次告警 -> 告警持续,不记录");
                    return;
                } else {
                    // 上一次记录是 未告警 ,本次告警 -> 开始告警
                    log.debug("上一次记录是 未告警 ,本次告警 -> 开始告警");
                    statusBackup.setAlarmRemove("1");
                }
            }
        }

        equipmentStatusBackupMapper.insert(statusBackup);

    }

    /**
     * 设置状态参数
      */
    private void setStatusCode(DeviceLog deviceLog, EquipmentStatusBackup statusBackup) {
        // 客户要求参数: 关机(0)/开机(1)/报警(2)/故障(3)运行(4)待机(5)
        if (deviceLog.getDeviceStatus().equals(DeviceRunStatusEnum.OFFLINE.getCode())) {
            statusBackup.setDeviceStatus("关机");
            statusBackup.setStatusCode("0");
        } else if (deviceLog.getDeviceStatus().equals(DeviceRunStatusEnum.ERROR.getCode())) {
            statusBackup.setDeviceStatus("故障");
            statusBackup.setStatusCode("3");
        } else {
            statusBackup.setDeviceStatus("开机");
            statusBackup.setStatusCode("1");
        }
    }

    @Override
    public void insertEquipmentUseBackup(List<DeviceUsageRecord> usageRecordList) {
        for (DeviceUsageRecord usageRecord : usageRecordList) {
            EquipmentUseBackup useBackup = new EquipmentUseBackup();
            useBackup.setDevice(deviceCode);
            useBackup.setPrimaryKey(usageRecord.getId());
            useBackup.setWorkDate(DateUtils.dateTime(usageRecord.getWorkingDate()));
            useBackup.setOnhours(usageRecord.getBootTime());
            useBackup.setWorkhours(usageRecord.getWorkingHours());
            equipmentUseBackupMapper.insert(useBackup);
        }
    }

    @Override
    public void insertProcessingDataBack(BaseProductInfo productInfo) {
        ProcessingDataBack processingData = new ProcessingDataBack();
        processingData.setPrimaryKey(productInfo.getId());
        processingData.setDeviceCode(deviceCode);
        processingData.setSerialNumber(productInfo.getProductCode());
        processingData.setUserNumber(productInfo.getOperator());
        processingData.setPowerused(productInfo.getConsumption().floatValue());
        processingDataMapper.insert(processingData);

    }
}
